package com.abel.bigwater.data.sanchuan

import com.abel.bigwater.data.BcdString
import com.abel.bigwater.data.mapper.DataMapper
import com.abel.bigwater.data.mapper.RtuMapper
import com.fasterxml.jackson.databind.ObjectMapper
import io.netty.buffer.Unpooled
import io.netty.channel.embedded.EmbeddedChannel
import io.netty.handler.timeout.IdleStateHandler
import org.joda.time.DateTime
import org.junit.Test
import org.junit.runner.RunWith
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.junit4.SpringRunner

@SpringBootTest
@RunWith(SpringRunner::class)
class SanchuanTcpHandlerTests {

    val firmId = "37"

    val firmCode = "yj-"

    @Autowired
    var dataMapper: DataMapper? = null

    @Autowired
    var rtuMapper: RtuMapper? = null

    /**
     * not depicted in protocol: 00 00 before start time.
     */
    @Test
    fun testGprsOnline() {
        val str1 = """68 00 a1 68 10 05 18 00 01 11 07 18 06 36 b0 00 00 00 7f 15 03 04 60 04 03 62 90 35 86 02 00 7d
2d b4 15 01 20 20 04 19 02 00 76 a8 f4 00 76 d5 86 00 77 03 bc 00 77 2d 38 00 77 5b 1e 00 77 86
52 00 77 bc 26 00 77 e4 6c 00 78 1b 9e 00 78 53 b6 00 78 89 c6 00 78 c4 a4 00 78 fe 74 00 79 34
7a 00 79 70 3e 00 79 b0 8a 00 79 f2 e8 00 7a 29 52 00 7a 5f 6c 00 7a 92 b6 00 7a cf a6 00 7b 06
ba 00 7b 39 f0 00 7b 73 48 00 7b b0 92 00 7b ea e4 00 7c 23 74 00 7c 5b 00 00 7c 90 7a 00 7c d1
ca 00 7d 10 d6 a9 16 
"""
        val handler = SanchuanTcpHandler(dataMapper!!, rtuMapper!!, firmId, firmCode)
        val ch = EmbeddedChannel(SanchuanDecoder(), handler)
        ch.writeInbound(Unpooled.buffer().writeBytes(BcdString.toByteArray(str1)))

        Thread.sleep(2 * 1000)
        lgr.info("Gprs test.")
    }

    /**
     * it meets protocol, and omits the 2 bytes: 00 00 before start time..
     */
    @Test
    fun testGprsOnlineNew() {
        val fmt = """68 00 9f 68 10 02 18 02 01 11 07 18 06 36 98 00 00 00 3b 11 04 04 60 04 01 97 80 19 02 02 00 f7
76 3c 20 20 04 09 02 00 00 01 a9 00 00 01 a9 00 00 01 a9 00 00 01 a9 00 00 01 a9 00 00 01 a9 00
00 01 a9 00 00 01 a9 00 00 01 a9 00 00 01 a9 00 00 01 a9 00 00 01 a9 00 00 01 a9 00 00 01 a9 00
00 01 a9 00 00 01 a9 00 00 01 a9 00 00 01 a9 00 00 01 a9 00 00 01 3f 00 f5 7b ac 00 f5 bf 5e 00
f5 fb b8 00 f6 34 84 00 f6 4f aa 00 f6 6a bc 00 f6 8c 7c 00 f6 c0 fc 00 f6 ec 76 00 f7 21 6e 00
f7 61 38 a1 16 
"""
        val handler = SanchuanTcpHandler(dataMapper!!, rtuMapper!!, firmId, firmCode)
        val ch = EmbeddedChannel(SanchuanDecoder(), handler)
        ch.writeInbound(Unpooled.buffer().writeBytes(BcdString.toByteArray(fmt)))

        Thread.sleep(2 * 1000)
        lgr.info("Gprs test.")
    }

    @Test
    fun testRecentWeek() {
        val handler = SanchuanTcpHandler(dataMapper!!, rtuMapper!!, firmId, firmCode)

        lgr.info("normal: ${handler.recentWeek(DateTime.now().minusHours(6))}")
        lgr.info("normal: ${handler.recentWeek(DateTime.now())}")

        lgr.info("null: ${handler.recentWeek(null)}")

        val dt0 = DateTime(1970, 1, 1, 0, 0)
        lgr.info("ad0: ${handler.recentWeek(dt0)}")

        lgr.info("after now: ${handler.recentWeek(DateTime.now().plusHours(1))}")

        lgr.info("min: ${handler.recentWeek(DateTime(Long.MIN_VALUE))}")
    }

    @Test
    fun testLoadPackets() {
        val handler = SanchuanTcpHandler(dataMapper!!, rtuMapper!!, firmId, firmCode)

        val rlist = handler.loadPduList("3606180711010018")
        assert(1 == rlist.size)

        lgr.info("${ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(rlist)}")
    }

    @Test
    fun testOutputFetach() {
        val fd = FetchData(null).apply {
            this.cmdWeekDetail = FetchCmdWeekDetail(3).also {
                it.dataType = FetchCmdWeekDetail.DetailDataType.TotalForward
                it.periodType = FetchCmdWeekDetail.DetailPeriodType.TenMinutes
            }

            this.timeInterval = 1
            this.pointNumber = 48
            this.startTime = DateTime(2018, 8, 16, 16, 0, 0)
        }

        val sp = SanchuanPacket().apply {
            this.ctrlb = CtrlbType.FetchDetail
            this.actrlb = 2
            this.data = fd
            this.meterId = BcdString.fromBcdString("3606180711010018", true)
        }

        Unpooled.buffer().apply {
            sp.fillBuffer(this)
            lgr.info("fetch data:\n${BcdString.hexString(this, this.readableBytes(), true)}")
        }
    }

    /**
     * write other pdu, so got additional pdu and game over:
     * 68 00 0b 68 f9 02 18 00 01 11 07 18 06 36 01 81 16
     */
    @Test
    fun testOtherPdu() {
        val data = MeterOfflineData(null).apply {
            this.flag = OfflineFlagType.GameOver
        }

        val sp = SanchuanPacket().apply {
            this.ctrlb = CtrlbType.Offline
            this.actrlb = 2
            this.data = data
            this.meterId = BcdString.fromBcdString("3606180711010018", true)
        }

        val handler = SanchuanTcpHandler(dataMapper!!, rtuMapper!!, firmId, firmCode)
        val ch = EmbeddedChannel(IdleStateHandler(2, 2, 2),
                SanchuanDecoder(), handler)
        ch.writeInbound(Unpooled.buffer().also { sp.fillBuffer(it) })

        Thread.sleep(6 * 1000)
    }


    companion object {
        private val lgr = LoggerFactory.getLogger(SanchuanTcpHandlerTests::class.java)
    }
}